import os,sqlite3,json,sys,shutil,datetime,time
from globle import *
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import TimeoutException

# current_path = os.path.abspath(__file__)
# current_directory = os.path.dirname(os.path.abspath(__file__))

# 存储不同用途的driver实例和对应的标签页句柄
from selenium.common.exceptions import WebDriverException, NoSuchWindowException

# 全局驱动状态存储
drivers = {
    'ticket': {'driver': None, 'handle': None},
    'tickettime': {'driver': None, 'handle': None},
    'departtime': {'driver': None, 'handle': None},
    'projecttime': {'driver': None, 'handle': None}
}

# 对应不同driver的初始化URL
DRIVER_URLS = {
    'ticket': "https://servicedesk.kylinos.cn/osp2016/agent/ticketCreate.php",
    'tickettime': "https://pms.kylinos.cn/sp/ebdfpage/card/1/1136952532863811584/0?jumplinkParamKey=1%2F1136952532863811584",
    'departtime': "https://pms.kylinos.cn/sp/ebdfpage/card/1/1136954186543661060/0?jumplinkParamKey=1%2F1136954186543661060",
    'projecttime': "https://pms.kylinos.cn/sp/ebdfpage/card/1/1149828479761825797/0?jumplinkParamKey=1%2F1149828479761825797"
}

def _get_browser_driver():
    """根据操作系统获取相应的浏览器driver（增加浏览器选项配置）"""
    if sys.platform.startswith('win'):
        options = webdriver.EdgeOptions()
        options.add_argument('--start-maximized')  # 启动即最大化
        options.add_argument('--no-sandbox')       # 解决沙箱问题（Windows可选）
        return webdriver.Edge(options=options)
    elif sys.platform.startswith('linux'):
        options = webdriver.ChromeOptions()
        options.add_argument('--start-maximized')
        options.add_argument('--no-sandbox')       # Linux必须，否则可能启动失败
        options.add_argument('--disable-dev-shm-usage')  # 禁用共享内存，避免Linux下崩溃
        return webdriver.Chrome(options=options)
    else:
        print(f"当前操作系统 {sys.platform} 不支持自动选择浏览器driver")
        return None

def _is_driver_process_alive(driver):
    """校验driver对应的浏览器进程是否存活（关键补充）"""
    if not driver:
        return False
    try:
        # 调用driver的进程检查方法（不同浏览器略有差异，这里用通用方式）
        driver.service.assert_process_still_running()
        return True
    except (WebDriverException, AttributeError):
        # WebDriverException：进程已退出；AttributeError：部分driver版本没有该方法，直接视为失效
        return False

def _is_driver_valid(driver, handle):
    """增强版校验：同时校验driver进程、handle有效性"""
    if not driver or not _is_driver_process_alive(driver):
        return False
    try:
        # 先切换到目标handle，再检查当前handle是否存在
        driver.switch_to.window(handle)
        # 再验证一次进程（避免切换过程中进程崩溃）
        return _is_driver_process_alive(driver)
    except (NoSuchWindowException, WebDriverException):
        # NoSuchWindowException：handle不存在；WebDriverException：切换失败（如driver已失效）
        return False

def release_driver(driver_type):
    """优化释放逻辑：确保标签页和进程彻底清理"""
    global drivers
    driver_info = drivers[driver_type]
    driver = driver_info['driver']
    handle = driver_info['handle']

    if not driver:
        return

    try:
        # 1. 先切换到目标标签页（若仍有效），再关闭
        if _is_driver_valid(driver, handle):
            driver.switch_to.window(handle)
            driver.close()  # 关闭当前标签页

        # 2. 检查driver是否还有其他存活标签页，无则退出浏览器进程
        remaining_handles = []
        if _is_driver_process_alive(driver):
            try:
                remaining_handles = driver.window_handles
            except WebDriverException:
                # 获取标签页列表失败，视为进程已不稳定，直接退出
                pass

        if not remaining_handles:
            try:
                driver.quit()  # 退出整个浏览器进程，释放资源
            except WebDriverException:
                # 进程可能已自动退出，忽略异常
                pass

    except Exception as e:
        print(f"释放 {driver_type} driver 时发生异常：{str(e)}")

    finally:
        # 强制重置状态，避免残留无效引用（核心保障）
        driver_info['driver'] = None
        driver_info['handle'] = None

def initialize_driver(driver_type, use_existing_browser=False):
    """优化初始化逻辑：确保状态干净、标签页正确"""
    global drivers
    driver_info = drivers[driver_type]

    # 1. 先彻底释放旧资源（无论是否有效，避免残留）
    release_driver(driver_type)

    # 2. 若需复用现有浏览器，查找存活的driver
    target_driver = None
    if use_existing_browser:
        for key in drivers:
            other_info = drivers[key]
            if _is_driver_valid(other_info['driver'], other_info['handle']):
                target_driver = other_info['driver']
                break  # 找到第一个存活的driver，复用它

    # 3. 若未找到复用的，创建新driver
    if not target_driver:
        target_driver = _get_browser_driver()
        if not target_driver:
            print(f"初始化 {driver_type} driver 失败：无法创建浏览器实例")
            return

    # 4. 在目标driver中打开新标签页并访问URL
    try:
        # 保存当前标签页（避免后续切换混乱）
        original_handle = target_driver.current_window_handle
        # 打开新标签页
        target_driver.execute_script("window.open('');")
        # 切换到新标签页（最新的handle）
        new_handle = target_driver.window_handles[-1]
        target_driver.switch_to.window(new_handle)
        # 访问目标URL
        target_driver.get(DRIVER_URLS[driver_type])
        # 记录状态（此时driver和handle均有效）
        driver_info['driver'] = target_driver
        driver_info['handle'] = new_handle
        print(f"初始化 {driver_type} driver 成功，标签页handle：{new_handle}")

    except Exception as e:
        print(f"初始化 {driver_type} driver 失败：{str(e)}")
        # 初始化失败，回滚操作（关闭新增的标签页，释放资源）
        try:
            if target_driver:
                # 切换回原始标签页，再关闭新标签页
                if original_handle in target_driver.window_handles:
                    target_driver.switch_to.window(original_handle)
                if new_handle in target_driver.window_handles:
                    target_driver.switch_to.window(new_handle)
                    target_driver.close()
                # 若目标driver是新创建的，直接退出进程
                if not use_existing_browser:
                    target_driver.quit()
        except:
            pass
        # 重置状态
        driver_info['driver'] = None
        driver_info['handle'] = None

def get_driver(driver_type, use_existing_browser=False):
    """获取driver：确保返回有效实例，无效则自动重建"""
    global drivers
    driver_info = drivers[driver_type]

    # 1. 校验当前实例是否有效，无效则重新初始化
    if not _is_driver_valid(driver_info['driver'], driver_info['handle']):
        initialize_driver(driver_type, use_existing_browser)

    # 2. 返回前再次切换到目标标签页（避免其他操作切换了标签页）
    if _is_driver_valid(driver_info['driver'], driver_info['handle']):
        driver_info['driver'].switch_to.window(driver_info['handle'])
        return driver_info['driver']
    else:
        print(f"获取 {driver_type} driver 失败：无法创建有效实例")
        return None

# 保持原有接口兼容（无需修改）
def initialize_webdriver():
    initialize_driver('ticket')

def get_webdriver():
    return get_driver('ticket')

def initialize_tickettimedriver(use_existing_browser=True):
    initialize_driver('tickettime', use_existing_browser)

def get_tickettimedriver(use_existing_browser=True):
    return get_driver('tickettime', use_existing_browser)

def initialize_departtimedriver(use_existing_browser=True):
    initialize_driver('departtime', use_existing_browser)

def get_departtimedriver(use_existing_browser=True):
    return get_driver('departtime', use_existing_browser)

def initialize_projecttimedriver(use_existing_browser=True):
    initialize_driver('projecttime', use_existing_browser)

def get_projecttimedriver(use_existing_browser=True):
    return get_driver('projecttime', use_existing_browser)

class Database:
    def __init__(self):
        self._data = None
        # 设置当前文件夹
        # self.current_directory =  current_directory
        # 找到当前文件夹下config文件
        self.config_path = os.path.join('res', 'config', 'config.json')
        # 获取文件内容
        default_folder_path = self.load_folder_path()
        # 数据库文件获取
        self.db_path = os.path.join(default_folder_path, 'res', 'db','备份')
        self.db_file = os.path.join(default_folder_path, 'res', 'db', 'kydetail.db')
        self.conn = sqlite3.connect(self.db_file)
        self.c = self.conn.cursor()

    def load_folder_path(self):
        if os.path.exists(self.config_path):
            try:
                with open(self.config_path, 'r') as f:
                    config = json.load(f)
                    return config.get('folder_path', '')
            except json.JSONDecodeError:
                print("Error: Invalid JSON format in config file.")
            except Exception as e:
                print(f"Error: {e}")
        else:
            print(f"Error: Config file '{self.config_path}' does not exist.")
        return ''
    
    def get_connection(self):
        return self.conn.cursor()
    
    def commit_database(self):
        if self.conn:
            self.conn.commit()

    def close_connection(self):
        if self.conn:
            self.conn.commit()
            self.conn.close()

    def backup_db(self):
        # 检查备份目录是否存在，如果不存在则创建
        if not os.path.exists(self.db_path):
            os.makedirs(self.db_path)
        
        # 生成备份文件名，带上当前时间戳以确保每次备份都不覆盖
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_file = os.path.join(self.db_path, f"backup_{timestamp}_{os.path.basename(self.db_file)}")
        
        # 备份数据库文件
        shutil.copy(self.db_file, backup_file)
        print(f"数据库备份完成: {backup_file}")

    def get_data_from_db(self, query, params=None):
        if params:
            self.c.execute(query, params)
        else:
            self.c.execute(query)
        result = self.c.fetchone()
        return result
    
    def get_datas_from_db(self, query, params=None):
        if params:
            self.c.execute(query, params)
        else:
            self.c.execute(query)
        result = self.c.fetchall()
        return result

    def execute_query(self, query, data=None):
        if data:
            self.c.execute(query, data)
        else:
            self.c.execute(query)

    def fetch_data_and_update_combobox(self, query, combobox):
        self.c.execute(query)
        data = self.c.fetchall()
        combobox.clear()
        for item in data:
            combobox.addItem(item[0])  # 假设combobox是Qt的下拉选择框对象

    # 通过where条件字段名，字段值，获取对应用户某条数据--单条查询
    def get_custom_data(self, custom_value_field):
        query = (
            f"SELECT * FROM integrator"
        )
        result = self.get_data_from_db(query)
        if result is not None:
            if custom_value_field == 'id':
                return result[0]
            elif custom_value_field == 'custom_name':
                return result[1]
            elif custom_value_field == 'custom_phone':
                return result[2]
            elif custom_value_field == 'serial_num':
                return result[3]
            elif custom_value_field == 'custom_company':
                return result[4]
            elif custom_value_field == 'custom_department':
                return result[5]
            elif custom_value_field == 'custom_default_area':
                return result[6]
            elif custom_value_field == 'default_saller':
                return result[7]
        else:
            # 处理查询结果为空的情况，例如记录日志或者返回默认值
            return None
        
    def get_integrator(self):
        if self._data is None:
            self._data = self._fetch_data_from_db()
        return self._data

    def _fetch_data_from_db(self):
        query = (
            f"SELECT * FROM integrator"
        )
        result = self.get_datas_from_db(query)
        return result if result is not None else []
    
    def final_integrator(self):
        self._data = None
        new_data = self._fetch_data_from_db()
        if new_data:  # 确保 new_data 不是 None 或空列表
            self._data = new_data
            event_emitter.notify("DataUpdated")
            return self._data
        else:
            print("No data returned from final_integrator")

    def get_default_set_data(self, default_value_field):
        default_set_query = f"SELECT * FROM default_set"
        result = self.get_data_from_db(default_set_query)
        if default_value_field == 'id':
            return result[0]
        elif default_value_field == 'my_account':
            return result[1]
        elif default_value_field == 'my_passwd':
            return result[2]
        elif default_value_field == 'default_name':
            return result[3]
        elif default_value_field == 'default_area':
            return result[4]
        elif default_value_field == 'default_time':
            return result[5]
        elif default_value_field == 'default_saller':
            return result[6]
        elif default_value_field == 'default_city':
            return result[7]
        elif default_value_field == 'default_district':
            return result[8]
        
    def get_ticket_data(self):
        c = self.conn.cursor()
        ticket_query = (
            "SELECT id, custom_name, custom_phone, serial_num,"
            "custom_company, custom_department,"
            "custom_default_area, ticket_title,"
            "ticket_code, question_ask, question_done,"
            "use_time, start_time, end_time, is_import,"
            "is_local, ticket_status, service_level, contract_id,"
            "product_id, l2_name, ticket_area "
            "FROM ticket WHERE ticket_status = 1"
        )
        c.execute(ticket_query)
        ticket_sheet = c.fetchone()
        ticket_data = []
        while ticket_sheet:
            ticket_data.append(ticket_sheet)
            ticket_sheet = c.fetchone()
        c.close()
        return ticket_data


# 定义一个自定义事件
class UserAddedEvent(object):
    def __init__(self, new_user_data):
        self.new_user_data = new_user_data
# 全局事件发射器
class EventEmmiter:
    def __init__(self):
        self.listeners = []

    def subscribe(self, listener):
        self.listeners.append(listener)

    def notify(self, event):
        for listener in self.listeners:
            listener(event)
# 实例化事件发射器
event_emitter = EventEmmiter()